;;;The StateWriter manages writing out changes to the grid each frame,
;;;for the python script to process.

(in-package "ACL2")

(include-book "../../include/src/io-utilities")
(include-book "cell")

(set-state-ok t)

;;Checks if file "statefile.txt" exists in this directory. If so,
;;(t |STATE| ) is returned. If not, (nil |STATE|) is returned.
;TODO the order of the mv return needs to be updated in the design doc (bool state) as opposed to (state bool)
(defun check-state-existence* (state)
  (mv-let (text err state)
    (file->string "statefile.txt" state)
    ;This "if" is a hack since DrRacket and ProofPad have 
    ;different + incompatible ideas about ignore declarations
    (if text
    	(mv (not err) state)
     (mv (not err) state))))

;;This takes a string generated by other functions in the state writer
;;and performs the actual IO      
(defun write-changes-io* (chrs gen-num state)
  (let ((outstring (chrs->str chrs)))
      (mv-let (err state)
      	(string-list->file (string-append "states/statefile_"
                                           (string-append
                                             (rat->str gen-num 0)
                                            	".txt"))
                                             (list outstring) state)
         	(if err state state))))

;;Given a cell, stringify out its X and Y components separated by a space
(defun cell->chrs* (cell)
  (append (str->chrs (rat->str (cell-x cell) 0))
          (append '(#\Space) (str->chrs (rat->str (cell-y cell) 0)))))

;;Given a list of cells, create a list of characters containing each cell,
;;in the format generated by cell->chrs*, separated by commas.    
(defun cells->chrs* (cells)
  (if (not cells)
      nil
      (append (cell->chrs* (car cells))
              (append (if (cdr cells) '(#\,) nil)
                      (cells->chrs* (cdr cells))))))

;;Given a list of integers, create a list of characters that is a
;;comma-separated list of the integers
(defun ints->chrs* (ints)
  (if (not ints)
      nil
      (append (str->chrs (rat->str (car ints) 0))
              (append (if (cdr ints) '(#\,) nil)
                      (ints->chrs* (cdr ints))))))


;;Write each point out to a file to be read in by the python script,
;;telling it which cells to toggle (live cells listed here become
;;dead, dead cells become alive).
;;If ruletype is "lifelike" this calls cells->chrs* to generate
;;the string. The cells will be written in a comma-separated list,
;;with the x and y coordinates separated by a space.
;;If ruletype is "elementary" this calls ints->chrs to generate
;;the string. The cells (integers) will be written in a comma separated 
;;list. If the ruletype is some other value, nil is returned and no io
;;is done. This calls write-changes-io* to write the strings out to
;;statefile.
(defun write-changes (changeset ruletype gen-num state)
    (if (string-equal "lifelike" ruletype)
      (write-changes-io* (cells->chrs* changeset) gen-num state)
      (if (string-equal "elementary" ruletype)
          (write-changes-io* (ints->chrs* changeset) gen-num state)
          state)))
             